package com.koron.system.org.service.impl;

import com.koron.bean.system.org.OrgBean;
import com.koron.bean.system.org.dto.OrgDto;
import com.koron.bean.system.org.query.OrgQuery;
import com.koron.bean.system.staff.StaffBean;
import com.koron.bean.system.staff.vo.EamUser;
import com.koron.bean.util.RedisUtils;
import com.koron.bean.util.UUIDUtils;
import com.koron.common.core.business.datadict.bean.po.SysDataDict;
import com.koron.common.core.business.datadict.bean.po.SysDataDictDetail;
import com.koron.common.core.business.datadict.service.SysDataDictService;
import com.koron.common.core.business.system.tree.TreeUtil;
import com.koron.common.core.util.HanyupinyinUtil;
import com.koron.system.common.util.TypeTreeVo;
import com.koron.system.org.bean.WorkFlowDepartment;
import com.koron.system.org.mapper.OrgMapper;
import com.koron.system.org.service.OrgService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName OrgServiceImpl
 * @description
 * @Author zhouj
 * @Date 2021/7/6 9:54
 */
@Transactional
@Service
@Slf4j
public class OrgServiceImpl implements OrgService, ApplicationRunner {

    @Autowired
    OrgMapper orgMapper;

    @Autowired
    SysDataDictService sysDataDictService;

    /**
     * redis组织缓存key前缀
     */
    private static final String key_prefix = "eam:org:id:";

    private static final long expire_time = 6 * 60 * 60;

    @Override
    public int insertOrg(EamUser staffBean, OrgBean orgBean) {

        //新增组织得 生成好全路径,存入数据库/添加组织首拼
        int i = 0;
        if (StringUtils.isEmpty(orgBean.getId())) {

            orgBean.setId(UUIDUtils.getUuid());
            orgBean.setCreateBy(staffBean.getAccount());
            orgBean.setCreateByName(staffBean.getName());
            orgBean.setCreateTime(new Date());
            orgBean.setNamePy(HanyupinyinUtil.getPinyinString(orgBean.getName()));
            OrgBean levelPathBean;
            orgBean.setLevelPath("/");
            orgBean.setLevelPathName("/");
            if (!StringUtils.isEmpty(orgBean.getParent())) {
                levelPathBean = orgMapper.queryParentLevelPath(orgBean.getParent());
                if (levelPathBean != null) {
                    String prefixPath = "/".equals(levelPathBean.getLevelPath()) ? "" : levelPathBean.getLevelPath();
                    String prefixPathName = "/".equals(levelPathBean.getLevelPathName()) ? "" : levelPathBean.getLevelPathName();
                    orgBean.setLevelPath(prefixPath + "/" + levelPathBean.getId());
                    orgBean.setLevelPathName(prefixPathName + "/" + levelPathBean.getName());
                }
            }
            i = orgMapper.insert(orgBean);
            RedisUtils.set(key_prefix + orgBean.getId(), orgBean);
        }
        return i;
    }


    @Override
    public int updateOrg(EamUser staffBean, OrgBean orgBean) {

        //新增组织得  生成好新的路径,存入数据库
        int i = 0;
        if (!StringUtils.isEmpty(orgBean.getId())) {
            //query pojo
            OrgBean preOrgBean = new OrgBean();
            preOrgBean.setId(orgBean.getId());

            preOrgBean = orgMapper.querySingleOrg(preOrgBean);

            orgBean.setUpdateBy(staffBean.getAccount());
            orgBean.setUpdateByName(staffBean.getName());
            orgBean.setUpdateTime(new Date());
            orgBean.setNamePy(HanyupinyinUtil.getPinyinString(orgBean.getName()));

            i = orgMapper.update(orgBean);

            if (!StringUtils.equals(preOrgBean.getName(), orgBean.getName())) {
                //修改子节点的路径
                String preLevelPathName = getFullLevelPathName(preOrgBean);
                String curLevelPathName = getFullLevelPathName(orgBean);
                orgMapper.updateChildrenLevelPathName(getFullLevelPath(preOrgBean), preLevelPathName, curLevelPathName);
            }
            RedisUtils.set(key_prefix + orgBean.getId(), orgBean);
        }
        return i;
    }

    private String getFullLevelPathName(OrgBean orgBean) {
        return orgBean.getLevelPathName() + "/" + orgBean.getName();
    }

    private String getFullLevelPath(OrgBean orgBean) {
        return orgBean.getLevelPath() + "/" + orgBean.getId();
    }

    @Override
    public int inUpOrg(EamUser staffBean, OrgBean orgBean) {

        int i;

        if (StringUtils.isEmpty(orgBean.getId())) {
            orgBean.setId(UUIDUtils.getUuid());
            orgBean.setCreateBy(staffBean.getAccount());
            orgBean.setCreateByName(staffBean.getName());
            orgBean.setCreateTime(new Date());
            i = orgMapper.insert(orgBean);
        } else {
            orgBean.setUpdateBy(staffBean.getAccount());
            orgBean.setUpdateByName(staffBean.getName());
            orgBean.setUpdateTime(new Date());
            i = orgMapper.update(orgBean);
        }
        RedisUtils.set(key_prefix + orgBean.getId(), orgBean);
        return i;

    }

    @Override
    public int deleteOrg(String id) {
        RedisUtils.delete(key_prefix + id);
        return orgMapper.softDelete(id);
    }

    @Override
    public List<StaffBean> queryStaffList(OrgBean orgBean) {
        return null;
    }

    @Override
    public int deleteOrgList(List<String> ids) {
        int i = orgMapper.deleteOrgList(ids);
        ids.forEach(id -> RedisUtils.delete(key_prefix + id));
        return i;
    }

    @Override
    public List<TypeTreeVo> queryOrgTree(OrgQuery orgQuery) {

        //引入权限控制--利用字段做控制,然后作为sql条件筛选
        if (orgQuery.getPermission()) {
            orgQuery.setOrgIds(getCurrUserOrgIds());
        }

        if (orgQuery.getPermissionAllapp()) {
            orgQuery.setOrgIds(getCurrUserAllOrgIds());
        }

        List<TypeTreeVo> list = orgMapper.queryOrgTree(orgQuery);
        List<TypeTreeVo> tree = TreeUtil.getTree(list);
        return tree;
    }

    @Override
    public List<OrgBean> queryNextOrgList(OrgQuery orgQuery) {
        //引入权限控制--利用字段做控制,然后作为sql条件筛选
        if (orgQuery.getPermission()) {
            orgQuery.setOrgIds(getCurrUserOrgIds());
        }

        List<OrgBean> orgBeans = orgMapper.queryNextOrgList(orgQuery);

        //将选中节点放在最前面
        String levelPath = orgQuery.getLevelPath();
        if (CollectionUtils.isNotEmpty(orgBeans) && StringUtils.isNotEmpty(levelPath)) {

            for (int i = 0; i < orgBeans.size(); i++) {
                if (levelPath.equals(orgBeans.get(i).getId())) {
                    orgBeans.add(0, orgBeans.remove(i));
                    break;
                }
            }

        }
        return orgBeans;
    }

    @Override
    public Long queryNextOrgListCount(OrgBean orgBean) {
        return orgMapper.queryNextOrgListCount(orgBean);
    }

    @Override
    public OrgBean querySingleOrg(OrgBean orgBean) {
        return orgMapper.querySingleOrg(orgBean);
    }

    @Override
    public List<WorkFlowDepartment> getWorkFlowDepartmentList() {
        return orgMapper.getWorkFlowDepartmentList();
    }

    @Override
    public int resetPy() {
        List<OrgBean> listByOrg = queryNextOrgList(new OrgQuery());
        listByOrg.forEach(p -> {
            p.setNamePy(HanyupinyinUtil.getPinyinString(p.getName()));
        });
        if (CollectionUtils.isEmpty(listByOrg)) {
            return 0;
        }

        return orgMapper.resetPy(listByOrg);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        try {
            log.info("开始加载组织缓存");
            initCache();
        } catch (Exception e) {
            log.error("缓存组织异常", e);
        }
    }

    private void initCache() {
        // 查询所有组织
        List<OrgBean> list = orgMapper.queryNextOrgList(new OrgQuery());
        // 放入缓存
        list.stream().forEach(i -> RedisUtils.set(key_prefix + i.getId(), i));
    }

    @Override
    public OrgBean queryDeptByOrgId(String orgId) {

        OrgBean orgBean = orgMapper.queryByOrgId(orgId);
        if (orgBean == null) {
            return null;
        }
        if ("2".equals(orgBean.getLevel())) {
            //本身为部门
            return orgBean;
        } else {
            //向上循环查询第一级部门
            String levelPath = orgBean.getLevelPath();
            String[] split = levelPath.split("/");
            for (int i = split.length - 1; i >= 0; i--) {
                OrgBean orgBean1 = orgMapper.queryByOrgId(split[i]);
                if (orgBean1 != null && "2".equals(orgBean1.getLevel())) {
                    return orgBean1;
                }
            }
        }
        return null;
    }

    @Override
    public List<OrgBean> queryDeptByOrgIdList(OrgDto orgDto) {

        List<OrgBean> orgBeans = queryByOrgIds(orgDto.getOrgIds());

        Assert.isTrue(CollectionUtils.isNotEmpty(orgBeans));

        //先找到水司下的全部部门
        OrgQuery orgBean = new OrgQuery();
        orgBean.setLevel("2");
        List<OrgBean> deptList = queryNextOrgList(orgBean);

        Map<String, String> map = new HashMap<>();
        deptList.forEach(p -> {
            map.put(p.getId(), p.getName());
        });

        for (OrgBean bean : orgBeans) {

            //本身就是部门,直接赋值返回
            String deptName = map.get(bean.getId());
            if (StringUtils.isNotEmpty(deptName)) {
                bean.setDeptId(bean.getId());
                bean.setDeptName(bean.getName());
                continue;
            }

            String levelPath = bean.getLevelPath();
            String[] split = levelPath.split("/");
            for (int i = split.length - 1; i >= 0; i--) {
                deptName = map.get(split[i]);
                if (StringUtils.isNotEmpty(deptName)) {
                    bean.setDeptId(split[i]);
                    bean.setDeptName(deptName);
                    break;
                }
            }
        }

        return orgBeans;
    }

    @Override
    public List<OrgBean> queryByOrgIds(List<String> orgIds) {
        Assert.isTrue(CollectionUtils.isNotEmpty(orgIds));
        return orgMapper.queryByOrgIds(orgIds);
    }

    public List<String> getOrgLevel(String orgId) {
        //根据orgId 获取当前层级及可允许修改层级 规则: 不能超过父级层级  不能小于子级层级
        List<String> arrayList = new ArrayList<>();

        //下面为获取可用列表
        try (SessionFactory factory = new SessionFactory()) {
            SysDataDict sysDataDict = sysDataDictService.getByClassifyIdAndCode(factory, "systemManagement", "system_org_level");
            List<SysDataDictDetail> sysDataDictDetailList = sysDataDict.getSysDataDictDetailList();
            if (CollectionUtils.isEmpty(sysDataDictDetailList)) {
                return arrayList;
            } else {
                arrayList = sysDataDictDetailList.stream().map(SysDataDictDetail::getKey).distinct().collect(Collectors.toList());
            }
        }

        OrgBean orgBean = orgMapper.queryByOrgId(orgId);
        Assert.notNull(orgBean, "组织不能为空");
        String level = orgBean.getLevel();

        int max = Integer.parseInt(arrayList.get(0));
        int min = Integer.parseInt(arrayList.get(arrayList.size() - 1));

        //根据组织id查询父级组织
        OrgBean parent = orgMapper.queryByOrgId(orgBean.getParent());
        if (!Objects.isNull(parent)) {
            max = Integer.parseInt(parent.getLevel());
        }
        //根据组织id查询最小子级
        List<OrgBean> childList = orgMapper.queryByParent(orgBean.getId());
        if (!CollectionUtils.isEmpty(childList)) {
            OrgBean minOrgBean = childList.get(0);
            min = Integer.parseInt(minOrgBean.getLevel());
        }

        List<String> result = new ArrayList<>();

        int finalMin = min;
        int finalMax = max;
        arrayList.forEach(p -> {
            int i = Integer.parseInt(p);
            if (i <= finalMin && i >= finalMax) {
                result.add(p);
            }
        });

        return result;
    }

    public Integer getSortByName(String name) {
        return orgMapper.getSortByName(name);
    }

}
